{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configurations for Colab"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "IN_COLAB = \"google.colab\" in sys.modules\n",
    "\n",
    "if IN_COLAB:\n",
    "    !apt install python-opengl\n",
    "    !apt install ffmpeg\n",
    "    !apt install xvfb\n",
    "    !pip install pyvirtualdisplay\n",
    "    !pip install gym[all]\n",
    "    from pyvirtualdisplay import Display\n",
    "    \n",
    "    # Start virtual display\n",
    "    dis = Display(visible=0, size=(400, 400))\n",
    "    dis.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 04. Dueling Network\n",
    "\n",
    "[Z. Wang et al., \"Dueling Network Architectures for Deep Reinforcement Learning.\" arXiv preprint arXiv:1511.06581, 2015.](https://arxiv.org/pdf/1511.06581.pdf)\n",
    "\n",
    "The proposed network architecture, which is named *dueling architecture*, explicitly separates the representation of state values and (state-dependent) action advantages. \n",
    "\n",
    "![fig1](https://user-images.githubusercontent.com/14961526/60322956-c2f0b600-99bb-11e9-9ed4-443bd14bc3b0.png)\n",
    "\n",
    "The dueling network automatically produces separate estimates of the state value function and advantage function, without any extra supervision. Intuitively, the dueling architecture can learn which states are (or are not) valuable, without having to learn the effect of each action for each state. This is particularly useful in states where its actions do not affect the environment in any relevant way. \n",
    "\n",
    "The dueling architecture represents both the value $V(s)$ and advantage $A(s, a)$ functions with a single deep model whose output combines the two to produce a state-action value $Q(s, a)$. Unlike in advantage updating, the representation and algorithm are decoupled by construction.\n",
    "\n",
    "$$A^\\pi (s, a) = Q^\\pi (s, a) - V^\\pi (s).$$\n",
    "\n",
    "The value function $V$ measures the how good it is to be in a particular state $s$. The $Q$ function, however, measures the the value of choosing a particular action when in this state. Now, using the definition of advantage, we might be tempted to construct the aggregating module as follows:\n",
    "\n",
    "$$Q(s, a; \\theta, \\alpha, \\beta) = V (s; \\theta, \\beta) + A(s, a; \\theta, \\alpha),$$\n",
    "\n",
    "where $\\theta$ denotes the parameters of the convolutional layers, while $\\alpha$ and $\\beta$ are the parameters of the two streams of fully-connected layers.\n",
    "\n",
    "Unfortunately, the above equation is unidentifiable in the sense that given $Q$ we cannot recover $V$ and $A$ uniquely; for example, there are uncountable pairs of $V$ and $A$ that make $Q$ values to zero. To address this issue of identifiability, we can force the advantage function estimator to have zero advantage at the chosen action. That is, we let the last module of the network implement the forward mapping.\n",
    "\n",
    "$$\n",
    "Q(s, a; \\theta, \\alpha, \\beta) = V (s; \\theta, \\beta) + \\big( A(s, a; \\theta, \\alpha) - \\max_{a' \\in |\\mathcal{A}|} A(s, a'; \\theta, \\alpha) \\big).\n",
    "$$\n",
    "\n",
    "This formula guarantees that we can recover the unique $V$ and $A$, but the optimization is not so stable because the advantages have to compensate any change to the optimal action’s advantage. Due to the reason, an alternative module that replaces the max operator with an average is proposed:\n",
    "\n",
    "$$\n",
    "Q(s, a; \\theta, \\alpha, \\beta) = V (s; \\theta, \\beta) + \\big( A(s, a; \\theta, \\alpha) - \\frac{1}{|\\mathcal{A}|} \\sum_{a'} A(s, a'; \\theta, \\alpha) \\big).\n",
    "$$\n",
    "\n",
    "Unlike the max advantage form, in this formula, the advantages only need to change as fast as the mean, so it increases the stability of optimization."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from typing import Dict, List, Tuple\n",
    "\n",
    "import gym\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from IPython.display import clear_output\n",
    "from torch.nn.utils import clip_grad_norm_"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replay buffer\n",
    "\n",
    "Please see *01.dqn.ipynb* for detailed description."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    \"\"\"A simple numpy replay buffer.\"\"\"\n",
    "\n",
    "    def __init__(self, obs_dim: int, size: int, batch_size: int = 32):\n",
    "        self.obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.next_obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.acts_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.rews_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.done_buf = np.zeros(size, dtype=np.float32)\n",
    "        self.max_size, self.batch_size = size, batch_size\n",
    "        self.ptr, self.size, = 0, 0\n",
    "\n",
    "    def store(\n",
    "        self,\n",
    "        obs: np.ndarray,\n",
    "        act: np.ndarray, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool,\n",
    "    ):\n",
    "        self.obs_buf[self.ptr] = obs\n",
    "        self.next_obs_buf[self.ptr] = next_obs\n",
    "        self.acts_buf[self.ptr] = act\n",
    "        self.rews_buf[self.ptr] = rew\n",
    "        self.done_buf[self.ptr] = done\n",
    "        self.ptr = (self.ptr + 1) % self.max_size\n",
    "        self.size = min(self.size + 1, self.max_size)\n",
    "\n",
    "    def sample_batch(self) -> Dict[str, np.ndarray]:\n",
    "        idxs = np.random.choice(self.size, size=self.batch_size, replace=False)\n",
    "        return dict(obs=self.obs_buf[idxs],\n",
    "                    next_obs=self.next_obs_buf[idxs],\n",
    "                    acts=self.acts_buf[idxs],\n",
    "                    rews=self.rews_buf[idxs],\n",
    "                    done=self.done_buf[idxs])\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self.size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dueling Network\n",
    "\n",
    "Carefully take a look at advantage and value layers separated from feature layer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Network(nn.Module):\n",
    "    def __init__(self, in_dim: int, out_dim: int):\n",
    "        \"\"\"Initialization.\"\"\"\n",
    "        super(Network, self).__init__()\n",
    "\n",
    "        # set common feature layer\n",
    "        self.feature_layer = nn.Sequential(\n",
    "            nn.Linear(in_dim, 128), \n",
    "            nn.ReLU(),\n",
    "        )\n",
    "        \n",
    "        # set advantage layer\n",
    "        self.advantage_layer = nn.Sequential(\n",
    "            nn.Linear(128, 128),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(128, out_dim),\n",
    "        )\n",
    "\n",
    "        # set value layer\n",
    "        self.value_layer = nn.Sequential(\n",
    "            nn.Linear(128, 128),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(128, 1),\n",
    "        )\n",
    "\n",
    "    def forward(self, x: torch.Tensor) -> torch.Tensor:\n",
    "        \"\"\"Forward method implementation.\"\"\"\n",
    "        feature = self.feature_layer(x)\n",
    "        \n",
    "        value = self.value_layer(feature)\n",
    "        advantage = self.advantage_layer(feature)\n",
    "\n",
    "        q = value + advantage - advantage.mean(dim=-1, keepdim=True)\n",
    "        \n",
    "        return q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DQN + DuelingNet Agent (w/o Double-DQN & PER)\n",
    "\n",
    "Here is a summary of DQNAgent class.\n",
    "\n",
    "| Method           | Note                                                 |\n",
    "| ---              | ---                                                  |\n",
    "|select_action     | select an action from the input state.               |\n",
    "|step              | take an action and return the response of the env.   |\n",
    "|compute_dqn_loss  | return dqn loss.                                     |\n",
    "|update_model      | update the model by gradient descent.                |\n",
    "|target_hard_update| hard update from the local model to the target model.|\n",
    "|train             | train the agent during num_frames.                   |\n",
    "|test              | test the agent (1 episode).                          |\n",
    "|plot              | plot the training progresses.                        |\n",
    "\n",
    "\n",
    "Aside from the dueling network architecture, the authors suggest to use Double-DQN and Prioritized Experience Replay as extra components for better performance. However, we don't implement them to simplify the tutorial. Here, DQNAgent is totally same as the one from *01.dqn.ipynb*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DQNAgent:\n",
    "    \"\"\"DQN Agent interacting with environment.\n",
    "    \n",
    "    Attribute:\n",
    "        env (gym.Env): openAI Gym environment\n",
    "        memory (ReplayBuffer): replay memory to store transitions\n",
    "        batch_size (int): batch size for sampling\n",
    "        epsilon (float): parameter for epsilon greedy policy\n",
    "        epsilon_decay (float): step size to decrease epsilon\n",
    "        max_epsilon (float): max value of epsilon\n",
    "        min_epsilon (float): min value of epsilon\n",
    "        target_update (int): period for target model's hard update\n",
    "        gamma (float): discount factor\n",
    "        dqn (Network): model to train and select actions\n",
    "        dqn_target (Network): target model to update\n",
    "        optimizer (torch.optim): optimizer for training dqn\n",
    "        transition (list): transition information including\n",
    "                           state, action, reward, next_state, done\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        env: gym.Env,\n",
    "        memory_size: int,\n",
    "        batch_size: int,\n",
    "        target_update: int,\n",
    "        epsilon_decay: float,\n",
    "        max_epsilon: float = 1.0,\n",
    "        min_epsilon: float = 0.1,\n",
    "        gamma: float = 0.99,\n",
    "    ):\n",
    "        \"\"\"Initialization.\n",
    "        \n",
    "        Args:\n",
    "            env (gym.Env): openAI Gym environment\n",
    "            memory_size (int): length of memory\n",
    "            batch_size (int): batch size for sampling\n",
    "            target_update (int): period for target model's hard update\n",
    "            epsilon_decay (float): step size to decrease epsilon\n",
    "            lr (float): learning rate\n",
    "            max_epsilon (float): max value of epsilon\n",
    "            min_epsilon (float): min value of epsilon\n",
    "            gamma (float): discount factor\n",
    "        \"\"\"\n",
    "        obs_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.n\n",
    "        \n",
    "        self.env = env\n",
    "        self.memory = ReplayBuffer(obs_dim, memory_size, batch_size)\n",
    "        self.batch_size = batch_size\n",
    "        self.epsilon = max_epsilon\n",
    "        self.epsilon_decay = epsilon_decay\n",
    "        self.max_epsilon = max_epsilon\n",
    "        self.min_epsilon = min_epsilon\n",
    "        self.target_update = target_update\n",
    "        self.gamma = gamma\n",
    "        \n",
    "        # device: cpu / gpu\n",
    "        self.device = torch.device(\n",
    "            \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "        )\n",
    "        print(self.device)\n",
    "\n",
    "        # networks: dqn, dqn_target\n",
    "        self.dqn = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "        self.dqn_target.eval()\n",
    "        \n",
    "        # optimizer\n",
    "        self.optimizer = optim.Adam(self.dqn.parameters())\n",
    "\n",
    "        # transition to store in memory\n",
    "        self.transition = list()\n",
    "        \n",
    "        # mode: train / test\n",
    "        self.is_test = False\n",
    "\n",
    "    def select_action(self, state: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Select an action from the input state.\"\"\"\n",
    "        # epsilon greedy policy\n",
    "        if self.epsilon > np.random.random():\n",
    "            selected_action = self.env.action_space.sample()\n",
    "        else:\n",
    "            selected_action = self.dqn(\n",
    "                torch.FloatTensor(state).to(self.device)\n",
    "            ).argmax()\n",
    "            selected_action = selected_action.detach().cpu().numpy()\n",
    "        \n",
    "        if not self.is_test:\n",
    "            self.transition = [state, selected_action]\n",
    "        \n",
    "        return selected_action\n",
    "\n",
    "    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool]:\n",
    "        \"\"\"Take an action and return the response of the env.\"\"\"\n",
    "        next_state, reward, done, _ = self.env.step(action)\n",
    "\n",
    "        if not self.is_test:\n",
    "            self.transition += [reward, next_state, done]\n",
    "            self.memory.store(*self.transition)\n",
    "    \n",
    "        return next_state, reward, done\n",
    "\n",
    "    def update_model(self) -> torch.Tensor:\n",
    "        \"\"\"Update the model by gradient descent.\"\"\"\n",
    "        samples = self.memory.sample_batch()\n",
    "\n",
    "        loss = self._compute_dqn_loss(samples)\n",
    "\n",
    "        self.optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        # we clip the gradients to have their norm less than or equal to 10.\n",
    "        clip_grad_norm_(self.dqn.parameters(), 10.0)\n",
    "        self.optimizer.step()\n",
    "\n",
    "        return loss.item()\n",
    "        \n",
    "    def train(self, num_frames: int, plotting_interval: int = 200):\n",
    "        \"\"\"Train the agent.\"\"\"\n",
    "        self.is_test = False\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        update_cnt = 0\n",
    "        epsilons = []\n",
    "        losses = []\n",
    "        scores = []\n",
    "        score = 0\n",
    "\n",
    "        for frame_idx in range(1, num_frames + 1):\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "\n",
    "            # if episode ends\n",
    "            if done:\n",
    "                state = self.env.reset()\n",
    "                scores.append(score)\n",
    "                score = 0\n",
    "\n",
    "            # if training is ready\n",
    "            if len(self.memory) >= self.batch_size:\n",
    "                loss = self.update_model()\n",
    "                losses.append(loss)\n",
    "                update_cnt += 1\n",
    "                \n",
    "                # linearly decrease epsilon\n",
    "                self.epsilon = max(\n",
    "                    self.min_epsilon, self.epsilon - (\n",
    "                        self.max_epsilon - self.min_epsilon\n",
    "                    ) * self.epsilon_decay\n",
    "                )\n",
    "                epsilons.append(self.epsilon)\n",
    "                \n",
    "                # if hard update is needed\n",
    "                if update_cnt % self.target_update == 0:\n",
    "                    self._target_hard_update()\n",
    "\n",
    "            # plotting\n",
    "            if frame_idx % plotting_interval == 0:\n",
    "                self._plot(frame_idx, scores, losses, epsilons)\n",
    "                \n",
    "        self.env.close()\n",
    "                \n",
    "    def test(self) -> List[np.ndarray]:\n",
    "        \"\"\"Test the agent.\"\"\"\n",
    "        self.is_test = True\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        done = False\n",
    "        score = 0\n",
    "        \n",
    "        frames = []\n",
    "        while not done:\n",
    "            frames.append(self.env.render(mode=\"rgb_array\"))\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "        \n",
    "        print(\"score: \", score)\n",
    "        self.env.close()\n",
    "        \n",
    "        return frames\n",
    "\n",
    "    def _compute_dqn_loss(self, samples: Dict[str, np.ndarray]) -> torch.Tensor:\n",
    "        \"\"\"Return dqn loss.\"\"\"\n",
    "        device = self.device  # for shortening the following lines\n",
    "        state = torch.FloatTensor(samples[\"obs\"]).to(device)\n",
    "        next_state = torch.FloatTensor(samples[\"next_obs\"]).to(device)\n",
    "        action = torch.LongTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n",
    "        reward = torch.FloatTensor(samples[\"rews\"].reshape(-1, 1)).to(device)\n",
    "        done = torch.FloatTensor(samples[\"done\"].reshape(-1, 1)).to(device)\n",
    "\n",
    "        # G_t   = r + gamma * v(s_{t+1})  if state != Terminal\n",
    "        #       = r                       otherwise\n",
    "        curr_q_value = self.dqn(state).gather(1, action)\n",
    "        next_q_value = self.dqn_target(next_state).max(\n",
    "            dim=1, keepdim=True\n",
    "        )[0].detach()\n",
    "        mask = 1 - done\n",
    "        target = (reward + self.gamma * next_q_value * mask).to(self.device)\n",
    "\n",
    "        # calculate dqn loss\n",
    "        loss = F.smooth_l1_loss(curr_q_value, target)\n",
    "\n",
    "        return loss\n",
    "\n",
    "    def _target_hard_update(self):\n",
    "        \"\"\"Hard update: target <- local.\"\"\"\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "                \n",
    "    def _plot(\n",
    "        self, \n",
    "        frame_idx: int, \n",
    "        scores: List[float], \n",
    "        losses: List[float], \n",
    "        epsilons: List[float],\n",
    "    ):\n",
    "        \"\"\"Plot the training progresses.\"\"\"\n",
    "        clear_output(True)\n",
    "        plt.figure(figsize=(20, 5))\n",
    "        plt.subplot(131)\n",
    "        plt.title('frame %s. score: %s' % (frame_idx, np.mean(scores[-10:])))\n",
    "        plt.plot(scores)\n",
    "        plt.subplot(132)\n",
    "        plt.title('loss')\n",
    "        plt.plot(losses)\n",
    "        plt.subplot(133)\n",
    "        plt.title('epsilons')\n",
    "        plt.plot(epsilons)\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Environment\n",
    "\n",
    "You can see the [code](https://github.com/openai/gym/blob/master/gym/envs/classic_control/cartpole.py) and [configurations](https://github.com/openai/gym/blob/master/gym/envs/__init__.py#L53) of CartPole-v0 from OpenAI's repository."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# environment\n",
    "env_id = \"CartPole-v0\"\n",
    "env = gym.make(env_id)\n",
    "if IN_COLAB:\n",
    "    env = gym.wrappers.Monitor(env, \"videos\", force=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set random seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[777]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seed = 777\n",
    "\n",
    "def seed_torch(seed):\n",
    "    torch.manual_seed(seed)\n",
    "    if torch.backends.cudnn.enabled:\n",
    "        torch.backends.cudnn.benchmark = False\n",
    "        torch.backends.cudnn.deterministic = True\n",
    "\n",
    "np.random.seed(seed)\n",
    "seed_torch(seed)\n",
    "env.seed(seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cpu\n"
     ]
    }
   ],
   "source": [
    "# parameters\n",
    "num_frames = 20000\n",
    "memory_size = 1000\n",
    "batch_size = 32\n",
    "target_update = 100\n",
    "epsilon_decay = 1 / 2000\n",
    "\n",
    "# train\n",
    "agent = DQNAgent(env, memory_size, batch_size, target_update, epsilon_decay)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "agent.train(num_frames)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test\n",
    "\n",
    "Run the trained agent (1 episode)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "score:  200.0\n"
     ]
    }
   ],
   "source": [
    "frames = agent.test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Render"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Define the Animation class */\n",
       "  function Animation(frames, img_id, slider_id, interval, loop_select_id){\n",
       "    this.img_id = img_id;\n",
       "    this.slider_id = slider_id;\n",
       "    this.loop_select_id = loop_select_id;\n",
       "    this.interval = interval;\n",
       "    this.current_frame = 0;\n",
       "    this.direction = 0;\n",
       "    this.timer = null;\n",
       "    this.frames = new Array(frames.length);\n",
       "\n",
       "    for (var i=0; i<frames.length; i++)\n",
       "    {\n",
       "     this.frames[i] = new Image();\n",
       "     this.frames[i].src = frames[i];\n",
       "    }\n",
       "    document.getElementById(this.slider_id).max = this.frames.length - 1;\n",
       "    this.set_frame(this.current_frame);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.get_loop_state = function(){\n",
       "    var button_group = document[this.loop_select_id].state;\n",
       "    for (var i = 0; i < button_group.length; i++) {\n",
       "        var button = button_group[i];\n",
       "        if (button.checked) {\n",
       "            return button.value;\n",
       "        }\n",
       "    }\n",
       "    return undefined;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.set_frame = function(frame){\n",
       "    this.current_frame = frame;\n",
       "    document.getElementById(this.img_id).src = this.frames[this.current_frame].src;\n",
       "    document.getElementById(this.slider_id).value = this.current_frame;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.next_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.min(this.frames.length - 1, this.current_frame + 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.previous_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.max(0, this.current_frame - 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.first_frame = function()\n",
       "  {\n",
       "    this.set_frame(0);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.last_frame = function()\n",
       "  {\n",
       "    this.set_frame(this.frames.length - 1);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.slower = function()\n",
       "  {\n",
       "    this.interval /= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.faster = function()\n",
       "  {\n",
       "    this.interval *= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_forward = function()\n",
       "  {\n",
       "    this.current_frame += 1;\n",
       "    if(this.current_frame < this.frames.length){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.first_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.last_frame();\n",
       "        this.reverse_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.last_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_reverse = function()\n",
       "  {\n",
       "    this.current_frame -= 1;\n",
       "    if(this.current_frame >= 0){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.last_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.first_frame();\n",
       "        this.play_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.first_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.pause_animation = function()\n",
       "  {\n",
       "    this.direction = 0;\n",
       "    if (this.timer){\n",
       "      clearInterval(this.timer);\n",
       "      this.timer = null;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.play_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = 1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_forward();}, this.interval);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.reverse_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = -1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_reverse();}, this.interval);\n",
       "  }\n",
       "</script>\n",
       "\n",
       "<div class=\"animation\" align=\"center\">\n",
       "    <img id=\"_anim_imgWBIWBFMQFXASRJJU\">\n",
       "    <br>\n",
       "    <input id=\"_anim_sliderWBIWBFMQFXASRJJU\" type=\"range\" style=\"width:350px\" name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\" onchange=\"animWBIWBFMQFXASRJJU.set_frame(parseInt(this.value));\"></input>\n",
       "    <br>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.slower()\">&#8211;</button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.first_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.previous_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.reverse_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.pause_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.play_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.next_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.last_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animWBIWBFMQFXASRJJU.faster()\">+</button>\n",
       "  <form action=\"#n\" name=\"_anim_loop_selectWBIWBFMQFXASRJJU\" class=\"anim_control\">\n",
       "    <input type=\"radio\" name=\"state\" value=\"once\" > Once </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"loop\" checked> Loop </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"reflect\" > Reflect </input>\n",
       "  </form>\n",
       "</div>\n",
       "\n",
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Instantiate the Animation class. */\n",
       "  /* The IDs given should match those used in the template above. */\n",
       "  (function() {\n",
       "    var img_id = \"_anim_imgWBIWBFMQFXASRJJU\";\n",
       "    var slider_id = \"_anim_sliderWBIWBFMQFXASRJJU\";\n",
       "    var loop_select_id = \"_anim_loop_selectWBIWBFMQFXASRJJU\";\n",
       "    var frames = new Array(0);\n",
       "    \n",
       "  frames[0] = \"\"\n",
       "  frames[1] = \"\"\n",
       "  frames[2] = \"\"\n",
       "  frames[3] = \"\"\n",
       "  frames[4] = \"\"\n",
       "  frames[5] = \"\"\n",
       "  frames[6] = \"\"\n",
       "  frames[7] = \"\"\n",
       "  frames[8] = \"\"\n",
       "  frames[9] = \"\"\n",
       "  frames[10] = \"\"\n",
       "  frames[11] = \"\"\n",
       "  frames[12] = \"\"\n",
       "  frames[13] = \"\"\n",
       "  frames[14] = \"\"\n",
       "  frames[15] = \"\"\n",
       "  frames[16] = \"\"\n",
       "  frames[17] = \"\"\n",
       "  frames[18] = \"\"\n",
       "  frames[19] = \"\"\n",
       "  frames[20] = \"\"\n",
       "  frames[21] = \"\"\n",
       "  frames[22] = \"\"\n",
       "  frames[23] = \"\"\n",
       "  frames[24] = \"\"\n",
       "  frames[25] = \"\"\n",
       "  frames[26] = \"\"\n",
       "  frames[27] = \"\"\n",
       "  frames[28] = \"\"\n",
       "  frames[29] = \"\"\n",
       "  frames[30] = \"\"\n",
       "  frames[31] = \"\"\n",
       "  frames[32] = \"\"\n",
       "  frames[33] = \"\"\n",
       "  frames[34] = \"\"\n",
       "  frames[35] = \"\"\n",
       "  frames[36] = \"\"\n",
       "  frames[37] = \"\"\n",
       "  frames[38] = \"\"\n",
       "  frames[39] = \"\"\n",
       "  frames[40] = \"\"\n",
       "  frames[41] = \"\"\n",
       "  frames[42] = \"\"\n",
       "  frames[43] = \"\"\n",
       "  frames[44] = \"\"\n",
       "  frames[45] = \"\"\n",
       "  frames[46] = \"\"\n",
       "  frames[47] = \"\"\n",
       "  frames[48] = \"\"\n",
       "  frames[49] = \"\"\n",
       "  frames[50] = \"\"\n",
       "  frames[51] = \"\"\n",
       "  frames[52] = \"\"\n",
       "  frames[53] = \"\"\n",
       "  frames[54] = \"\"\n",
       "  frames[55] = \"\"\n",
       "  frames[56] = \"\"\n",
       "  frames[57] = \"\"\n",
       "  frames[58] = \"\"\n",
       "  frames[59] = \"\"\n",
       "  frames[60] = \"\"\n",
       "  frames[61] = \"\"\n",
       "  frames[62] = \"\"\n",
       "  frames[63] = \"\"\n",
       "  frames[64] = \"\"\n",
       "  frames[65] = \"\"\n",
       "  frames[66] = \"\"\n",
       "  frames[67] = \"\"\n",
       "  frames[68] = \"\"\n",
       "  frames[69] = \"\"\n",
       "  frames[70] = \"\"\n",
       "  frames[71] = \"\"\n",
       "  frames[72] = \"\"\n",
       "  frames[73] = \"\"\n",
       "  frames[74] = \"\"\n",
       "  frames[75] = \"\"\n",
       "  frames[76] = \"\"\n",
       "  frames[77] = \"\"\n",
       "  frames[78] = \"\"\n",
       "  frames[79] = \"\"\n",
       "  frames[80] = \"\"\n",
       "  frames[81] = \"\"\n",
       "  frames[82] = \"\"\n",
       "  frames[83] = \"\"\n",
       "  frames[84] = \"\"\n",
       "  frames[85] = \"\"\n",
       "  frames[86] = \"\"\n",
       "  frames[87] = \"\"\n",
       "  frames[88] = \"\"\n",
       "  frames[89] = \"\"\n",
       "  frames[90] = \"\"\n",
       "  frames[91] = \"\"\n",
       "  frames[92] = \"\"\n",
       "  frames[93] = \"\"\n",
       "  frames[94] = \"\"\n",
       "  frames[95] = \"\"\n",
       "  frames[96] = \"\"\n",
       "  frames[97] = \"\"\n",
       "  frames[98] = \"\"\n",
       "  frames[99] = \"\"\n",
       "  frames[100] = \"\"\n",
       "  frames[101] = \"\"\n",
       "  frames[102] = \"\"\n",
       "  frames[103] = \"\"\n",
       "  frames[104] = \"\"\n",
       "  frames[105] = \"\"\n",
       "  frames[106] = \"\"\n",
       "  frames[107] = \"\"\n",
       "  frames[108] = \"\"\n",
       "  frames[109] = \"\"\n",
       "  frames[110] = \"\"\n",
       "  frames[111] = \"\"\n",
       "  frames[112] = \"\"\n",
       "  frames[113] = \"\"\n",
       "  frames[114] = \"\"\n",
       "  frames[115] = \"\"\n",
       "  frames[116] = \"\"\n",
       "  frames[117] = \"\"\n",
       "  frames[118] = \"\"\n",
       "  frames[119] = \"\"\n",
       "  frames[120] = \"\"\n",
       "  frames[121] = \"\"\n",
       "  frames[122] = \"\"\n",
       "  frames[123] = \"\"\n",
       "  frames[124] = \"\"\n",
       "  frames[125] = \"\"\n",
       "  frames[126] = \"\"\n",
       "  frames[127] = \"\"\n",
       "  frames[128] = \"\"\n",
       "  frames[129] = \"\"\n",
       "  frames[130] = \"\"\n",
       "  frames[131] = \"\"\n",
       "  frames[132] = \"\"\n",
       "  frames[133] = \"\"\n",
       "  frames[134] = \"\"\n",
       "  frames[135] = \"\"\n",
       "  frames[136] = \"\"\n",
       "  frames[137] = \"\"\n",
       "  frames[138] = \"\"\n",
       "  frames[139] = \"\"\n",
       "  frames[140] = \"\"\n",
       "  frames[141] = \"\"\n",
       "  frames[142] = \"\"\n",
       "  frames[143] = \"\"\n",
       "  frames[144] = \"\"\n",
       "  frames[145] = \"\"\n",
       "  frames[146] = \"\"\n",
       "  frames[147] = \"\"\n",
       "  frames[148] = \"\"\n",
       "  frames[149] = \"\"\n",
       "  frames[150] = \"\"\n",
       "  frames[151] = \"\"\n",
       "  frames[152] = \"\"\n",
       "  frames[153] = \"\"\n",
       "  frames[154] = \"\"\n",
       "  frames[155] = \"\"\n",
       "  frames[156] = \"\"\n",
       "  frames[157] = \"\"\n",
       "  frames[158] = \"\"\n",
       "  frames[159] = \"\"\n",
       "  frames[160] = \"\"\n",
       "  frames[161] = \"\"\n",
       "  frames[162] = \"\"\n",
       "  frames[163] = \"\"\n",
       "  frames[164] = \"\"\n",
       "  frames[165] = \"\"\n",
       "  frames[166] = \"\"\n",
       "  frames[167] = \"\"\n",
       "  frames[168] = \"\"\n",
       "  frames[169] = \"\"\n",
       "  frames[170] = \"\"\n",
       "  frames[171] = \"\"\n",
       "  frames[172] = \"\"\n",
       "  frames[173] = \"\"\n",
       "  frames[174] = \"\"\n",
       "  frames[175] = \"\"\n",
       "  frames[176] = \"\"\n",
       "  frames[177] = \"\"\n",
       "  frames[178] = \"\"\n",
       "  frames[179] = \"\"\n",
       "  frames[180] = \"\"\n",
       "  frames[181] = \"\"\n",
       "  frames[182] = \"\"\n",
       "  frames[183] = \"\"\n",
       "  frames[184] = \"\"\n",
       "  frames[185] = \"\"\n",
       "  frames[186] = \"\"\n",
       "  frames[187] = \"\"\n",
       "  frames[188] = \"\"\n",
       "  frames[189] = \"\"\n",
       "  frames[190] = \"\"\n",
       "  frames[191] = \"\"\n",
       "  frames[192] = \"\"\n",
       "  frames[193] = \"\"\n",
       "  frames[194] = \"\"\n",
       "  frames[195] = \"\"\n",
       "  frames[196] = \"\"\n",
       "  frames[197] = \"\"\n",
       "  frames[198] = \"\"\n",
       "  frames[199] = \"\"\n",
       "\n",
       "\n",
       "    /* set a timeout to make sure all the above elements are created before\n",
       "       the object is initialized. */\n",
       "    setTimeout(function() {\n",
       "        animWBIWBFMQFXASRJJU = new Animation(frames, img_id, slider_id, 50, loop_select_id);\n",
       "    }, 0);\n",
       "  })()\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "if IN_COLAB:  # for colab\n",
    "    import base64\n",
    "    import glob\n",
    "    import io\n",
    "    import os\n",
    "\n",
    "    from IPython.display import HTML, display\n",
    "\n",
    "\n",
    "    def ipython_show_video(path: str) -> None:\n",
    "        \"\"\"Show a video at `path` within IPython Notebook.\"\"\"\n",
    "        if not os.path.isfile(path):\n",
    "            raise NameError(\"Cannot access: {}\".format(path))\n",
    "\n",
    "        video = io.open(path, \"r+b\").read()\n",
    "        encoded = base64.b64encode(video)\n",
    "\n",
    "        display(HTML(\n",
    "            data=\"\"\"\n",
    "            <video alt=\"test\" controls>\n",
    "            <source src=\"data:video/mp4;base64,{0}\" type=\"video/mp4\"/>\n",
    "            </video>\n",
    "            \"\"\".format(encoded.decode(\"ascii\"))\n",
    "        ))\n",
    "\n",
    "    list_of_files = glob.glob(\"videos/*.mp4\")\n",
    "    latest_file = max(list_of_files, key=os.path.getctime)\n",
    "    print(latest_file)\n",
    "    ipython_show_video(latest_file)\n",
    "    \n",
    "else:  # for jupyter\n",
    "    from matplotlib import animation\n",
    "    from JSAnimation.IPython_display import display_animation\n",
    "    from IPython.display import display\n",
    "\n",
    "\n",
    "    def display_frames_as_gif(frames: List[np.ndarray]) -> None:\n",
    "        \"\"\"Displays a list of frames as a gif, with controls.\"\"\"\n",
    "        patch = plt.imshow(frames[0])\n",
    "        plt.axis('off')\n",
    "\n",
    "        def animate(i):\n",
    "            patch.set_data(frames[i])\n",
    "\n",
    "        anim = animation.FuncAnimation(\n",
    "            plt.gcf(), animate, frames = len(frames), interval=50\n",
    "        )\n",
    "        display(display_animation(anim, default_mode='loop'))\n",
    "\n",
    "\n",
    "    # display \n",
    "    display_frames_as_gif(frames)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
